package com.yuanduo_app.widget;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Looper;
import android.os.Vibrator;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;
import android.widget.ImageView;

import com.baozi.Zxing.camera.CameraManager;
import com.baozi.Zxing.decoding.CaptureActivityHandler;
import com.baozi.Zxing.decoding.CaptureInterface;
import com.baozi.Zxing.decoding.InactivityTimer;
import com.baozi.Zxing.utils.ZXingUtils;
import com.baozi.Zxing.view.ViewfinderView;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.xujl.fastlib.utils.AppManager;
import com.xujl.task.Emitter;
import com.xujl.task.RxExecutor;
import com.xujl.task.RxHelper;
import com.xujl.task.RxLife;
import com.xujl.task.RxLifeList;
import com.xujl.task.Task;

import com.yuanduo_app.MainActivityControl;
import com.yuanduo_app.MainApplication;
import com.yuanduo_app.R;
import com.yuanduo_app.bridge.DataModule;
import com.yuanduo_app.consts.PermissionGroup;
import com.yuanduo_app.manager.RNModuleManager;

import java.io.IOException;
import java.util.Vector;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import pub.devrel.easypermissions.EasyPermissions;

import static android.content.Context.AUDIO_SERVICE;
import static android.content.Context.VIBRATOR_SERVICE;

public class QrCodeView extends FrameLayout implements SurfaceHolder.Callback, CaptureInterface {
    private ViewfinderView viewfinderView;
    private SurfaceView mPreviewView;
    private InactivityTimer inactivityTimer;
    private boolean hasSurface;
    private boolean playBeep;
    private static final float BEEP_VOLUME = 0.10f;
    private static final long VIBRATE_DURATION = 200L;
    private boolean vibrate;
    private Vector<BarcodeFormat> decodeFormats;
    private String characterSet;
    private ImageView scanLine;
    private TranslateAnimation translateAnimation;
    private CaptureActivityHandler handler;
    private MediaPlayer mediaPlayer;

    public QrCodeView (@NonNull Context context) {
        super(context);
        init(context);
    }

    public QrCodeView (@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public QrCodeView (@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init (Context context) {
        // 初始化 CameraManager
        CameraManager.init(getContext().getApplicationContext());
        addView(LayoutInflater.from(context).inflate(R.layout.widget_scanner, null));
        viewfinderView = (ViewfinderView) findViewById(R.id.mo_scanner_viewfinder_view);
        scanLine = (ImageView) findViewById(R.id.capture_scan_line);
        mPreviewView = findViewById(R.id.mo_scanner_preview_view);
        inactivityTimer = new InactivityTimer(AppManager.getAppManager().findActivity(MainActivityControl.class));
        initAnimation();
    }

    private void initAnimation () {
        //扫描动画
        translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_PARENT, 0.0f, Animation
                .RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT, 0.0f, Animation.RELATIVE_TO_PARENT,
                0.9f);
        translateAnimation.setDuration(2500);
        translateAnimation.setRepeatCount(-1);
        translateAnimation.setRepeatMode(Animation.REVERSE);
    }

    private void initCamera (SurfaceHolder surfaceHolder) {

        try {
            CameraManager.get().openDriver(surfaceHolder);
        } catch (Exception ioe) {
            return;
        }
        if (handler == null) {
            handler = new CaptureActivityHandler(Looper.getMainLooper(), this, AppManager.getAppManager().findActivity(MainActivityControl.class), decodeFormats,
                    characterSet);
        }
    }

    public void startAnimation () {
        scanLine.startAnimation(translateAnimation);
    }

    public void stopAnimation () {
        if (scanLine == null || scanLine.getAnimation() == null) {
            return;
        }
        scanLine.getAnimation().cancel();
    }

    public void lightOn () {
        CameraManager.get().openLight();
    }

    public void lightOff () {
        CameraManager.get().offLight();
    }

    private RxLifeList mLifeList = new RxLifeList();

    public void startScan () {
        SurfaceHolder surfaceHolder = mPreviewView.getHolder();
        if (hasSurface) {
            initCamera(surfaceHolder);
        } else {
            surfaceHolder.addCallback(this);
            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
        decodeFormats = null;
        characterSet = null;

        playBeep = true;
        AudioManager audioService = (AudioManager) getContext().getSystemService(AUDIO_SERVICE);
        if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
            playBeep = false;
        }
        initBeepSound();
        vibrate = true;
    }

    private void initBeepSound () {
        if (playBeep && mediaPlayer == null) {
            AppManager.getAppManager().findActivity(MainActivityControl.class).setVolumeControlStream(AudioManager.STREAM_MUSIC);
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setOnCompletionListener(beepListener);

            AssetFileDescriptor file = getResources().openRawResourceFd(
                    com.maning.libraryzxing.R.raw.mo_scanner_beep);
            try {
                mediaPlayer.setDataSource(file.getFileDescriptor(),
                        file.getStartOffset(), file.getLength());
                file.close();
                mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
                mediaPlayer.prepare();
            } catch (IOException e) {
                mediaPlayer = null;
            }
        }
    }

    public void stopScan () {
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        CameraManager.get().closeDriver();
    }

    @Override
    public void surfaceCreated (SurfaceHolder holder) {
        if (!EasyPermissions.hasPermissions(MainApplication.getApplication(), PermissionGroup.QR_CODE)) {
            //没有授权时发起授权
            AppManager.getAppManager().findActivity(MainActivityControl.class).requestRuntimePermissions(PermissionGroup.QR_CODE);
            RxExecutor.getInstance().executeTask(new RxHelper.RecycleTask(true, 1000, 10) {
                @Override
                public void count (int count) {
                    if (EasyPermissions.hasPermissions(MainApplication.getApplication(), PermissionGroup.QR_CODE)) {
                        surfaceCreated(holder);
                    }
                }

                @Override
                public void bindLife (RxLife rxLife) {
                    super.bindLife(rxLife);
                    mLifeList.add(rxLife);
                }
            });
            return;
        }
        mLifeList.onDestroy();
        if (!hasSurface) {
            hasSurface = true;
            RxExecutor.getInstance()
                    .executeTask(new Task<Object>() {
                        @Override
                        public void run (Emitter<Object> emitter) throws Exception {
                            super.run(emitter);
                            initCamera(holder);
                        }

                    });
        }
    }

    @Override
    public void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed (SurfaceHolder holder) {
        hasSurface = false;
    }

    @Override
    public void drawViewfinder () {
        viewfinderView.drawViewfinder();
    }

    @Override
    public ViewfinderView getViewfinderView () {
        return viewfinderView;
    }

    @Override
    public void handleDecode (Result result, Bitmap barcode) {
        inactivityTimer.onActivity();
        playBeepSoundAndVibrate();
        String recode = ZXingUtils.recode(result.toString());
        // 数据返回
        final DataModule dataModule = RNModuleManager.getInstance().getModule(DataModule.class);
        dataModule.sendEvent(DataModule.ON_SCAN_FINISH_BLOCK, recode);
    }

    @Override
    public Handler getHandler () {
        return handler;
    }

    private void playBeepSoundAndVibrate () {
        if (playBeep && mediaPlayer != null) {
            mediaPlayer.start();
        }
        if (vibrate) {
            Vibrator vibrator = (Vibrator) getContext().getSystemService(VIBRATOR_SERVICE);
            vibrator.vibrate(VIBRATE_DURATION);
        }
    }

    private final MediaPlayer.OnCompletionListener beepListener = mediaPlayer -> mediaPlayer.seekTo(0);

    protected void onPause () {
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        CameraManager.get().closeDriver();
    }

    protected void onResume () {
        startScan();
    }

    public void onDestroy () {
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        CameraManager.get().closeDriver();
        inactivityTimer.shutdown();
        if (translateAnimation != null) {
            translateAnimation.cancel();
            translateAnimation = null;
        }
    }
}
